package jvs.sh;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;

import jvs.peer.util.Log;

/**
 * @author qiangli
 * 
 */
public class BasicCommandInterpreter implements Interpreter {
	private String crlf = "\r\n";
	private Console console;
	private IShell shell;

	public void parse(String req) {

		if (Log.DEBUG) {
			Log.log(this, "parse input: " + req);
		}
		try {
			if (req == null || req.length() == 0) {
				return;
			}
			String cmdline = null;
			String data = null;
			int idx = req.indexOf("\r\n");
			int tlen = 1;
			if (idx == -1) {
				idx = req.indexOf("\n");
				if (idx == -1) {
					idx = req.indexOf("\r");
				}
			} else {
				tlen = 2;
			}
			if (idx == -1) {
				cmdline = req;
			} else {
				cmdline = req.substring(0, idx);
				idx += tlen;
				if (req.length() > idx) {
					data = req.substring(idx);
				}
			}

			String cmd = null;
			String args = null;

			// parse command
			String[] sa = split(cmdline, 2);
			cmd = (sa.length == 0) ? null : sa[0].toUpperCase();
			args = (sa.length > 1) ? sa[1] : null;

			//
			if (cmd != null && cmd.length() > 0) {
				if (shell.isConnected()) {
					execute(cmd, args, data);
				}
			}
		} catch (Throwable e) {
			// e.printStackTrace();
			print(e);
		}
	}

	private String[] split(String s, int limit) {
		if (s == null) {
			return new String[0];
		}
		s = s.trim();
		if (s.length() == 0) {
			return new String[0];
		}
		String[] sa = s.split("\\s+", limit);
		return sa;
	}

	protected void print(String s) {
		out(s);
	}

	protected void err(String msg) {
		console.err(msg + crlf);
	}

	private void print(Throwable e) {
		err(e.getMessage());
	}

	protected void ok(String s) {
		console.ok(s + crlf);
	}

	private void out(String s) {
		console.out(s + crlf);
	}

	public void setConsole(Console console) {
		this.console = console;
	}

	public void setShell(IShell shell) {
		this.shell = shell;
	}

	protected void execute(String line, String param, String data)
			throws Exception {
		if (Log.DEBUG) {
			Log.log(this, "execute cmd: " + line + " params: " + param
					+ " last access: ");
		}
		// line not null
		String s = shell.getEnv("crlf");
		crlf = (s == null ? "\r\n" : s);

		int idx = line.lastIndexOf("/");
		String cmd = (idx > 0) ? line.substring(idx + 1) : line;
		//
		shell.setLastAccess(System.currentTimeMillis());
		if (cmd.equals("SHELL")) {
			shell(param);
		} else if (cmd.equals("CONNECT") || cmd.equals("HI")
				|| cmd.equals("HELLO")) {
			connect(param);
		} else if (cmd.equals("DISCONNECT") || cmd.equals("BYE")
				|| cmd.equals("EXIT") || cmd.equals("QUIT")) {
			bye(param);
		} else if (cmd.equals("IP")) {
			ip(param);
		} else if (cmd.equals("PING")) {
			ping(param);
		} else {
			ni(cmd, param);
		}
	}

	private void shell(String param) {
	}

	private void connect(String args) {
		ok("Welcome. "+shell.id());
	}
	
	protected void bye(String args) throws Exception {
		ok("Bye "+shell.id());
		//
		shell.exit();
	}
	
	protected void ping(String args) throws Exception {
		String[] pa = split(args, 1);
		if (pa.length == 0) {
			err("Missing argument");
			return;
		}
		String peer = pa[0];
		boolean rc = shell.ping(peer);
		if (rc) {
			ok(peer + " is available");
		} else {
			ok(peer + " is not available");
		}
	}
	
	private String ip(String args) throws Exception {
		Enumeration<?> nis = NetworkInterface.getNetworkInterfaces();
		StringBuilder sb = new StringBuilder();
		NetworkInterface ni = (NetworkInterface) nis.nextElement();
		Enumeration<?> iis = ni.getInetAddresses();
		while (iis.hasMoreElements()) {
			InetAddress ia = ((InetAddress) iis.nextElement());
			if (ia.isLoopbackAddress()) {
				continue;
			}
			String addr = ia.getHostAddress();
			sb.append(addr);
			sb.append(" ");
		}
		return sb.toString();
	}
	
	protected void ni(String cmd, String args) {
		err(cmd + " not supported.");
	}
}
